package com.fpx.open.platform.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.fpx.open.platform.common.constant.ErrorCodeConstant;
import com.fpx.open.platform.common.constant.SysConstant;
import com.fpx.open.platform.common.util.Cryptogram;
import com.fpx.open.platform.common.util.DateUtil;
import com.fpx.open.platform.dao.mapper3.ApplicationMapper;
import com.fpx.open.platform.dao.mapper3.CustomerMapper;
import com.fpx.open.platform.dao.mapper3.RelAppUserInfoMapper;
import com.fpx.open.platform.dao.mapper3.RelUserCustomerMapper;
import com.fpx.open.platform.dao.mapper3.UserInfoExtMapper;
import com.fpx.open.platform.dao.mapper3.UserInfoMapper;
import com.fpx.open.platform.domain.Application;
import com.fpx.open.platform.domain.Customer;
import com.fpx.open.platform.domain.RelAppUserInfo;
import com.fpx.open.platform.domain.RelUserCustomer;
import com.fpx.open.platform.domain.RelUserCustomerKey;
import com.fpx.open.platform.domain.UserInfo;
import com.fpx.open.platform.domain.UserInfoExt;
import com.fpx.open.platform.domain.exception.ServiceException;
import com.fpx.open.platform.service.CustomerService;

/**
 * 操作客户相关信息服务类,用户权限和客户权限查询和授权以及验证
 * 
 * @author sunkey
 * @date Mar 25, 2013 10:37:49 AM
 * @version 1.0.0
 * @copyright fpx.com
 */
//@Service(value = "customerService")
public class CustomerServiceImpl implements CustomerService {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	@Resource
	private UserInfoMapper userInfoMapper;

	@Resource
	private CustomerMapper customerMapper;

	@Resource
	private UserInfoExtMapper userInfoExtMapper;

	@Resource
	private RelAppUserInfoMapper relAppUserInfoMapper;
	
//	@Resource
//	private RelAppCustomerMapper relAppCustomerMapper;
	
	@Resource
	private RelUserCustomerMapper relUserCustomerMapper;
	
	@Resource
	private ApplicationMapper applicationMapper;

	/**
	 * @see com.fpx.open.platform.service.api.web.manager.CustomerService.securityValidate
	 */
	public String securityValidate(Integer customerId, String token,
			Integer appId, String ip) throws ServiceException {
		if (logger.isDebugEnabled()) {
			logger.debug("customerId :" + customerId + ", token :" + token);
		}

		UserInfo userInfo = null;
		try {
			userInfo = userInfoMapper.selectByToken(token);
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}
		
		if (null == userInfo) {
			return ErrorCodeConstant.E_0055;
		}
		
		if(SysConstant.EFFECT_NO == userInfo.getIsEffect()){
			return ErrorCodeConstant.E_0056;
		}
		
		if(!isExsitRelAppUser(userInfo.getUserId(), appId)){
			return ErrorCodeConstant.E_0051;
		}
		//忽略校验customer id
		Map<Integer,Integer> appMap = initNoCheckCustomerId();
		if(!appMap.containsKey(appId)){
			if (!isExistRelUserCustomer(customerId, userInfo.getUserId())) {
				return ErrorCodeConstant.E_0059;
			}
		}
		if(userInfo.getExpireday() != 0){
			// 根据密钥进行token解密
			token = Cryptogram.decrypt(token);
	
			if (token.length() <= 14) { // 必须大于14（后14位为日期）
				return ErrorCodeConstant.E_0056;
			}
	
			// 取token的前(usid+username+password)
			String timestamp = token.substring(token.length() - 14);
	
			// 判断token是否失效
			boolean isInvalid = this.isExpire(timestamp, userInfo.getExpireday());
			if (!isInvalid){
				return ErrorCodeConstant.E_0056;
			}
		}

		return null;
	}
	
	/**
	 * @see com.fpx.open.platform.service.api.CustomerService.queryCustomer(Integer customerId)
	 */
	public Customer queryCustomer(Integer customerId) throws ServiceException {
		if (logger.isDebugEnabled()) {
			logger.debug("customerId={}", customerId);
		}

		Customer customer = null;
		try {
			customer = customerMapper.selectByPrimaryKey(customerId);
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}

		return customer;
	}
	
	/**
	 * @see com.fpx.open.platform.service.api.CustomerService.queryCustomer(String companyCode) 
	 */
	public Customer queryCustomerByCompnayCode(String companyCode, String customerType) throws ServiceException {
		if (logger.isDebugEnabled()) {
			logger.debug("companyCode={}", companyCode);
		}
		
		Customer customer = null;
		try {
			Map<String, String> conditionMap = new HashMap<String, String>();
			conditionMap.put("comapnyCode", companyCode);
			conditionMap.put("type", customerType);
			customer = customerMapper.selectByCompanyCodeType(conditionMap);
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}
		
		return customer;
	}

	/**
	 * @see com.com.fpx.open.platform.service.api.CustomerService.editAccountToken
	 */
	public void editAccountToken(Integer userId, String token, Date encryptDate)
			throws ServiceException {
		if (logger.isDebugEnabled()) {
			logger.debug("UserId={}, token={}", userId, token);
		}
		try {
			UserInfo userInfo = new UserInfo();
			userInfo.setUserId(userId);
			userInfo.setToken(token);
			userInfo.setDateUpdated(encryptDate);
			userInfoMapper.updateByPrimaryKeySelective(userInfo);
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}
	}

	/**
	 * @see com.com.fpx.open.platform.service.api.CustomerService.queryUserInfo
	 */
	public UserInfo queryUserInfo(String token) throws ServiceException {
		if (logger.isDebugEnabled()) {
			logger.debug("token={}", token);
		}
		UserInfo userInfo = null;
		try {
			userInfo = userInfoMapper.selectByToken(token);
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}
		return userInfo;
	}

	/**
	 * @see com.fpx.open.platform.service.api.CustomerService.queryUserInfo(String userName, String password)
	 */
	public UserInfo queryUserInfo(String userName, String password) throws ServiceException {
		if (logger.isDebugEnabled()) {
			logger.debug("userName={},password={}", userName, password);
		}
		UserInfo userInfo = new UserInfo();
		try {
			userInfo.setUserName(userName);
			userInfo.setPassword(password);
			userInfo = userInfoMapper.selectByNamePwd(userInfo);
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}
		return userInfo;
	}
	
	/**
	 * @see com.com.fpx.open.platform.service.api.CustomerService.queryUserInfoExt
	 */
	@Override
	public UserInfoExt queryUserInfoExt(String oldToken) throws ServiceException {
		if (logger.isDebugEnabled()) {
			logger.debug("oldToken={}", oldToken);
		}
		UserInfoExt userInfoExt = null;
		try {
			userInfoExt = userInfoExtMapper.selectByToken(oldToken);
			if(null == userInfoExt){
				throw new ServiceException("userInfoExt is empty",
						ErrorCodeConstant.E_0053);
			}
			UserInfo userInfo = userInfoMapper.selectByPrimaryKey(userInfoExt.getUserId());
			
			userInfo.setRelUserCustomers(queryRelUserCustomers(userInfo.getUserId()));
			
			userInfoExt.setUserInfo(userInfo);
		} catch (ServiceException e) { 
			throw e;
		}  catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}
		return userInfoExt;
	}
	
	/**
	 * @see com.fpx.open.platform.service.api.CustomerService.queryApplications(Integer userId)
	 */
	public List<Application> queryApplications(Integer userId) throws ServiceException{
		
		Map<String, Object> conditionMap = new HashMap<String, Object>();
		List<Integer> appIds = new ArrayList<Integer>();
		
		List<RelAppUserInfo> relAppUserInfos = queryRelAppUserInfos(userId);
		for (RelAppUserInfo relAppUserInfo : relAppUserInfos) {
			appIds.add(relAppUserInfo.getAppId());
		}
		
		conditionMap.put("list", appIds);
		
		try {
			
			List<Application> applications = applicationMapper.listByPrimaryKeys(conditionMap);
			
			return applications;
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}
	}
	
	
	private List<RelUserCustomer> queryRelUserCustomers(Integer userId) throws ServiceException{
		List<RelUserCustomer> relUserCustomers = relUserCustomerMapper.listByUserId(userId);
		if(null == relUserCustomers || relUserCustomers.isEmpty()){
			throw new ServiceException("relUserCustomers is empty",
					ErrorCodeConstant.E_0059);
		}
		return relUserCustomers;
	}
	
	private List<RelAppUserInfo> queryRelAppUserInfos(Integer userId) throws ServiceException{
		List<RelAppUserInfo> relAppUserInfos = relAppUserInfoMapper.listByUserId(userId);
		if(null == relAppUserInfos || relAppUserInfos.isEmpty()){
			throw new ServiceException("relUserCustomers is empty",
					ErrorCodeConstant.E_0059);
		}
		return relAppUserInfos;
	}
	
	/**
	 * 是否存在应用与用户的关系
	 *
	 * @param userId
	 * @param appId 应用ID
	 * @return 存在返回true
	 * @throws ServiceException
	 */
	private boolean isExsitRelAppUser(Integer userId, Integer appId)
			throws ServiceException {
		RelAppUserInfo relAppUserInfo = new RelAppUserInfo();
		relAppUserInfo.setAppId(appId);
		relAppUserInfo.setUserId(userId);

		try {
			relAppUserInfo = relAppUserInfoMapper
					.selectByPrimaryKey(relAppUserInfo);
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}

		if (relAppUserInfo == null || relAppUserInfo.getIsEffect() == SysConstant.EFFECT_NO) {
			return  false;
		} 

		return true;
	}

	/**
	 *是否存在应用和客户的授权关系
	 *
	 * @param customerId
	 * @param appId
	 * @return 存在授权关系返回true, 授权app直接返回true
	 * @throws ServiceException 
	 */
	private boolean isExistRelUserCustomer(Integer customerId, Integer userId) throws ServiceException{
		
		RelUserCustomerKey key = new RelUserCustomerKey();
		key.setCustomerId(customerId);
		key.setUserId(userId);
		RelUserCustomer relUserCustomer = null;
		try {
			relUserCustomer = relUserCustomerMapper.selectByPrimaryKey(key);
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}
		if (null == relUserCustomer || relUserCustomer.getIsEffect() != SysConstant.EFFECT_YES) {
			return false;
		}
		
		return true;
	}
	
	/**
	 *是否存在应用和客户的授权关系
	 *
	 * @param customerId
	 * @param appId
	 * @return 存在授权关系返回true
	 * @throws ServiceException 
	 */
	/*
	@SuppressWarnings("unused")
	@Deprecated
	private boolean isExistRelAppCustomer(Integer customerId, Integer appId) throws ServiceException{
		
		RelAppCustomerKey key = new RelAppCustomerKey();
		key.setCustomerId(customerId);
		key.setAppId(appId);
		RelAppCustomer relAppCustomer = null;
		try {
			relAppCustomer = relAppCustomerMapper.selectByPrimaryKey(key);
		} catch (Exception e) {
			logger.error("DB access failer", e);
			throw new ServiceException("DB access failer",
					ErrorCodeConstant.E_0104);
		}
		if (null == relAppCustomer || relAppCustomer.getIsEffect() != SysConstant.EFFECT_YES) {
			return false;
		}
		
		return true;
	}
	*/
	/**
	 * 是否过期
	 * 
	 * @param timestamp 时间戳
	 * @return boolean true为过期
	 */
	private boolean isExpire(String timestamp, int expireDay) {

		Date date = DateUtil.parse(timestamp, "yyyyMMddHHmmss");

		if (null == date){
			return false;
		}

		int dif = (int) ((new Date().getTime() - date.getTime()) / (1000 * 60 * 60 * 24));
		if (dif > expireDay){
			return false;
		}

		return true;
	}
	/**
	 * 初始化不需要校验Customer ID的功能
	 * @return
	 */
	private Map<Integer,Integer> initNoCheckCustomerId(){
		Map<Integer,Integer> map = new HashMap<Integer,Integer>();
		//授权
		map.put(Application.APP_AUTHORITH, Application.APP_AUTHORITH);
		//注册
		map.put(Application.APP_REGISTER, Application.APP_REGISTER);
		//查询订单变动
		map.put(Application.APP_XMS_ORDERCHANGE, Application.APP_XMS_ORDERCHANGE);
		//ODA验证
		map.put(Application.APP_XMS_ODA, Application.APP_XMS_ODA);
		//查询公司分拨点
		map.put(Application.APP_XMS_COMP, Application.APP_XMS_COMP);
		return map;
	}

	/**
     * 根据用户ID查对应的客户信息
     * @param strUserId        用户ID
     * @return List<Customer>  客户信息列表
     */
	@Override
	public List<Customer> queryComapnyIdByUserId(String strUserId) throws ServiceException{
		if(strUserId == null){
			throw new ServiceException("method findtShipperSupporter strCmId is null",ErrorCodeConstant.E_0003);
		}
		return customerMapper.selectComapnyIdByUserId(strUserId);
	}

}
